package utils

import (
	"errors"
	"fmt"
	"reflect"
)

type SliceItemCompareFn func(item interface{}) bool
type SliceCompareWith2ItemFn func(leftItem interface{}, rightItem interface{}) bool
func SliceFindWhere(src interface{}, compare SliceItemCompareFn) (interface{}, error) {
	srcVal := reflect.ValueOf(src)
	srckind := srcVal.Kind()

	if srckind != reflect.Slice && srckind != reflect.Array {
		return nil, errors.New("SliceFindWhere only supoort slice and array type")
	}

	destVal := reflect.MakeSlice(srcVal.Type(), 0, 0)
	for i := 0; i < srcVal.Len(); i++ {
		item := srcVal.Index(i).Interface()
		if isMatch := compare(item); isMatch {
			//destVal = append(destVal.Call(), item)
			destVal = reflect.Append(destVal, srcVal.Index(i))
		}
	}

	return destVal.Interface(), nil
}

//查找第一个符合条件的item
func SliceFindFirstWhere(src interface{}, compare SliceItemCompareFn) (interface{}, error) {
	srcVal := reflect.ValueOf(src)
	srckind := srcVal.Kind()

	if srckind != reflect.Slice && srckind != reflect.Array {
		return nil, errors.New("SliceFindWhere only supoort slice and array type")
	}

	for i := 0; i < srcVal.Len(); i++ {
		item := srcVal.Index(i).Interface()
		if isMatch := compare(item); isMatch {
			//destVal = append(destVal.Call(), item)
			return item, nil
		}
	}

	return nil, nil
}

func SliceIsIn(haystack interface{}, needle interface{}) (bool, error) {
	sVal := reflect.ValueOf(haystack)
	kind := sVal.Kind()
	if kind == reflect.Slice || kind == reflect.Array {
		for i := 0; i < sVal.Len(); i++ {
			if sVal.Index(i).Interface() == needle {
				return true, nil
			}
		}

		return false, nil
	}

	return false, errors.New("SliceIsIn only supoort slice and array type")
}

func SliceAny(src interface{}, compare SliceItemCompareFn) (bool, error) {
	srcVal := reflect.ValueOf(src)
	srckind := srcVal.Kind()

	if srckind != reflect.Slice && srckind != reflect.Array {
		return false, errors.New("SliceAny only supoort slice and array type")
	}

	for i := 0; i < srcVal.Len(); i++ {
		item := srcVal.Index(i).Interface()
		if isMatch := compare(item); isMatch {
			//destVal = append(destVal.Call(), item)
			return true, nil
		}
	}

	return false, nil
}


func SliceFindFirstWhere2(src interface{}, rightItem interface{}, compare SliceCompareWith2ItemFn) (interface{}, error) {
	srcVal := reflect.ValueOf(src)
	srckind := srcVal.Kind()

	if srckind != reflect.Slice && srckind != reflect.Array {
		return nil, errors.New("SliceFindWhere only supoort slice and array type")
	}

	for i := 0; i < srcVal.Len(); i++ {
		item := srcVal.Index(i).Interface()
		if isMatch := compare(item, rightItem); isMatch {
			//destVal = append(destVal.Call(), item)
			return item, nil
		}
	}

	return nil, nil
}
//
//代码源自：https://blog.csdn.net/youngwhz1/article/details/83026263
/* 在slice中去除重复的元素，其中a必须是已经排序的序列。
 * params:
 *   a: slice对象，如[]string, []int, []float64, ...
 * return:
 *   []interface{}: 已经去除重复元素的新的slice对象
 */
func SliceRemoveDuplicate(a interface{}) (ret []interface{}) {
	if reflect.TypeOf(a).Kind() != reflect.Slice {
		fmt.Printf("<SliceRemoveDuplicate> <a> is not slice but %T\n", a)
		return ret
	}

	va := reflect.ValueOf(a)
	for i := 0; i < va.Len(); i++ {
		if i > 0 && reflect.DeepEqual(va.Index(i-1).Interface(), va.Index(i).Interface()) {
			continue
		}
		ret = append(ret, va.Index(i).Interface())
	}

	return ret
}


/*
 * 在Slice指定位置插入元素。
 * params:
 *   s: slice对象，类型为[]interface{}
 *   index: 要插入元素的位置索引
 *   value: 要插入的元素
 * return:
 *   已经插入元素的slice，类型为[]interface{}
 */
func SliceInsert(s []interface{}, index int, value interface{}) []interface{} {
	rear := append([]interface{}{}, s[index:]...)
	return append(append(s[:index], value), rear...)
}


/*
 * 删除Slice中的元素。
 * params:
 *   s: slice对象，类型为[]interface{}
 *   index: 要删除元素的索引
 * return:
 *   已经删除指定元素的slice，类型为[]interface{}
 * 说明：返回的序列与传入的序列地址不发生变化(但是传入的序列内容已经被修改，不能再使用)
 */
func SliceRemove(s []interface{}, index int) []interface{} {
	return append(s[:index], s[index+1:]...)
}


//TODO 后续增加slice动态̬append
